Core.Storage.Trace = function(listener) {
	this.tracking = false;
	this.listener = listener;
	
	this.current = {};
	this.previous = {};
	this.storages = {};
};

Core.Storage.Trace.prototype = {
	
	/**
	 * Starts the data flow tracking.
	 */
	start: function() {
		this.previous = this.current;
		this.current = {};
		
		this.tracking = true;
	},
	
	/**
	 * Stops the data flow tracking.
	 * Differentially registers & unregisters listener from storages paths.
	 */
	stop: function() {
		var	curr = this.current, prev = this.previous, 
			storages = this.storages, o = this.listener;
		
		Object.each(prev, function(_, sid) {
			Object.each(prev[sid], function(_, path) {
				if(!curr[sid] || !curr[sid][path]) { storages[sid].unregister(path, o); }
			});
		});
		Object.each(curr, function(_, sid) {
			Object.each(curr[sid], function(_, path) {
				if(!prev[sid] || !prev[sid][path]) { storages[sid].register(path, o); }
			});
		});
		this.tracking = false;
	},
	
	/**
	 * Disposes the trace.
	 * Unregisters listener from all observed storages paths.
	 */
	dispose: function() {
		var	curr = this.current, storages = this.storages, o = this.listener;
		
		Object.each(curr, function(_, sid) {
			Object.each(curr[sid], function(_, path) {
				storages[sid].unregister(path, o);
			});
		});
		this.current = {};
		this.previous = {};
		this.tracking = false;
	},
	
	/**
	 * Logs the path and storage if in tracking mode.
	 * Will use this data for differential registering & unregistering the listener from the storages paths.
	 * 
	 * @param String path
	 * @param Object storage
	 */
	track: function(path, storage) {
		var sid = Core.uid(storage);

		if(this.tracking) {
			if(!this.storages[sid]) { this.storages[sid] = storage; }
			if(!this.current[sid]) { this.current[sid] = {}; }
			this.current[sid][path] = true;
		}
	}
};